/**
 * @file authservice.cpp
 * @brief 用户认证服务类实现文件
 *
 * 实现用户认证的所有业务逻辑，包括：
 * - 用户注册、登录、登出的完整流程
 * - JWT令牌的管理和自动刷新
 * - 用户信息的JSON序列化和反序列化
 * - 本地用户数据的持久化存储
 * - 认证状态的实时监控和处理
 */

#include "../include/authservice.h"
#include "../include/config.h"
#include <QJsonDocument>    // JSON文档处理
#include <QJsonArray>       // JSON数组处理
#include <QDebug>           // 调试输出

/**
 * @brief AuthService构造函数
 * @param parent 父对象指针
 *
 * 初始化认证服务的所有组件：
 * 1. 创建API客户端并建立连接
 * 2. 设置信号槽连接处理各种认证事件
 * 3. 从本地存储恢复用户信息（如果存在）
 */
AuthService::AuthService(QObject *parent)
    : QObject(parent)
    , m_apiClient(new ApiClient(Config::getApiBaseUrl(), this))  // 创建API客户端
{
    // === 建立信号槽连接 ===
    // 处理API响应
    connect(m_apiClient, &ApiClient::requestFinished,
            this, &AuthService::onApiResponse);
    // 处理认证失效事件
    connect(m_apiClient, &ApiClient::authenticationRequired,
            this, &AuthService::onAuthenticationRequired);
    // 处理令牌刷新事件
    connect(m_apiClient, &ApiClient::tokenRefreshed,
            this, &AuthService::onTokenRefreshed);

    // === 恢复用户信息 ===
    /* 从本地存储恢复用户信息的过程：
     * 1. 检查QSettings中是否存在"user_info"键
     * 2. 读取存储的JSON字节数组
     * 3. 将字节数组转换为JSON文档
     * 4. 提取JSON对象并解析为UserInfo结构
     *
     * 存储格式示例：
     * QSettings中的"user_info"键值：
     * QByteArray: "{\"user_id\":123,\"username\":\"player123\",\"email\":\"player@example.com\",...}"
     */
    QSettings settings;
    if (settings.contains("user_info")) {
        // 从QSettings读取JSON字节数组并转换为JSON对象
        QJsonObject userObj = QJsonDocument::fromJson(
            settings.value("user_info").toByteArray()).object();
        // 解析JSON对象为UserInfo结构体
        m_currentUser = parseUserInfo(userObj);
    }
}

/**
 * @brief 用户注册
 * @param username 用户名（3-20个字符，字母数字下划线）
 * @param password 密码（6-50个字符）
 * @param email 邮箱地址（有效的邮箱格式）
 *
 * 向服务器发送用户注册请求，构建JSON数据并通过API客户端发送。
 */
void AuthService::registerUser(const QString &username, const QString &password, const QString &email)
{
    // === 设置待处理操作标识 ===
    m_pendingOperation = "register";

    // === 构建注册请求数据 ===
    /* JSON数据构建示例：
     * 输入参数：
     * username = "newplayer123"
     * password = "securePassword123"
     * email = "newplayer@example.com"
     *
     * 构建的JSON对象：
     * {
     *   "username": "newplayer123",
     *   "password": "securePassword123",
     *   "email": "newplayer@example.com"
     * }
     *
     * 发送的HTTP请求体：
     * POST /api/v1/auth/register
     * Content-Type: application/json
     *
     * {"username":"newplayer123","password":"securePassword123","email":"newplayer@example.com"}
     */
    QJsonObject data;
    data["username"] = username;    // 用户名字段
    data["password"] = password;    // 密码字段（服务器端会进行哈希处理）
    data["email"] = email;          // 邮箱字段

    // === 发送注册请求 ===
    m_apiClient->post("/api/v1/auth/register", data);
}

/**
 * @brief 用户登录
 * @param username 用户名或邮箱地址
 * @param password 用户密码
 * @param rememberMe 是否记住登录状态（影响令牌过期时间）
 *
 * 向服务器发送登录请求，成功后会收到访问令牌和刷新令牌。
 */
void AuthService::login(const QString &username, const QString &password, bool rememberMe)
{
    // === 设置待处理操作标识 ===
    m_pendingOperation = "login";

    // === 构建登录请求数据 ===
    /* JSON数据构建示例：
     * 输入参数：
     * username = "player123"
     * password = "myPassword"
     * rememberMe = true
     *
     * 构建的JSON对象：
     * {
     *   "username": "player123",
     *   "password": "myPassword",
     *   "remember_me": true
     * }
     *
     * 发送的HTTP请求体：
     * POST /api/v1/auth/login
     * Content-Type: application/json
     *
     * {"username":"player123","password":"myPassword","remember_me":true}
     *
     * 预期的服务器响应：
     * {
     *   "success": true,
     *   "data": {
     *     "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     *     "refresh_token": "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     *     "user_info": {
     *       "user_id": 123,
     *       "username": "player123",
     *       "email": "player@example.com",
     *       "role": "user",
     *       "permissions": ["read", "write"]
     *     }
     *   },
     *   "timestamp": 1640995200
     * }
     */
    QJsonObject data;
    data["username"] = username;        // 用户名或邮箱
    data["password"] = password;        // 用户密码
    data["remember_me"] = rememberMe;   // 记住登录状态标志

    // === 发送登录请求 ===
    m_apiClient->post("/api/v1/auth/login", data);
}

void AuthService::logout(bool allDevices)
{
    m_pendingOperation = "logout";

    QJsonObject data;
    data["all_devices"] = allDevices;

    m_apiClient->post("/api/v1/auth/logout", data);
}

/**
 * @brief 验证当前访问令牌的有效性
 *
 * 向服务器发送令牌验证请求，确认当前令牌是否仍然有效。
 * 通常在应用启动时调用，检查保存的令牌是否过期。
 */
void AuthService::validateToken()
{
    // === 检查认证状态 ===
    if (!isAuthenticated()) {
        emit authenticationRequired();  // 没有令牌，需要重新登录
        return;
    }

    // === 发送验证请求 ===
    /* 令牌验证请求：
     * POST /api/v1/auth/validate
     * Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
     * Content-Type: application/json
     *
     * {}  // 空的JSON对象，令牌在Authorization头中
     *
     * 预期响应（有效令牌）：
     * {
     *   "success": true,
     *   "data": {
     *     "valid": true,
     *     "expires_at": "2024-01-01T13:00:00Z"
     *   }
     * }
     *
     * 预期响应（无效令牌）：
     * {
     *   "success": false,
     *   "error_code": "TOKEN_EXPIRED",
     *   "error_message": "访问令牌已过期"
     * }
     */
    m_pendingOperation = "validate";
    m_apiClient->post("/api/v1/auth/validate", QJsonObject{});
}

/**
 * @brief 刷新访问令牌
 *
 * 使用刷新令牌获取新的访问令牌，延长用户的登录状态。
 */
void AuthService::refreshToken()
{
    // === 检查刷新令牌 ===
    QString refreshToken = m_apiClient->getRefreshToken();
    if (refreshToken.isEmpty()) {
        emit authenticationRequired();  // 没有刷新令牌，需要重新登录
        return;
    }

    // === 构建刷新请求 ===
    /* 令牌刷新请求示例：
     * POST /api/v1/auth/refresh
     * Content-Type: application/json
     *
     * {
     *   "refresh_token": "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     * }
     *
     * 预期响应（刷新成功）：
     * {
     *   "success": true,
     *   "data": {
     *     "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",  // 新的访问令牌
     *     "expires_in": 3600
     *   }
     * }
     */
    QJsonObject data;
    data["refresh_token"] = refreshToken;

    m_pendingOperation = "refresh";
    m_apiClient->post("/api/v1/auth/refresh", data);
}

/**
 * @brief 忘记密码 - 发送重置邮件
 * @param email 用户邮箱地址
 *
 * 向指定邮箱发送密码重置链接，用户可以通过邮件中的链接重置密码。
 */
void AuthService::forgotPassword(const QString &email)
{
    m_pendingOperation = "forgot_password";

    // === 构建忘记密码请求 ===
    /* 忘记密码请求示例：
     * POST /api/v1/auth/forgot-password
     * Content-Type: application/json
     *
     * {
     *   "email": "user@example.com"
     * }
     *
     * 预期响应（邮件发送成功）：
     * {
     *   "success": true,
     *   "data": {
     *     "message": "密码重置邮件已发送",
     *     "email": "user@example.com"
     *   }
     * }
     *
     * 预期响应（邮箱不存在）：
     * {
     *   "success": false,
     *   "error_code": "EMAIL_NOT_FOUND",
     *   "error_message": "该邮箱地址未注册"
     * }
     */
    QJsonObject data;
    data["email"] = email;

    // 注意：这个API端点可能需要根据实际后端实现调整
    m_apiClient->post("/api/v1/auth/forgot-password", data);
}

/**
 * @brief 重置密码
 * @param token 密码重置令牌（从邮件链接中获取）
 * @param newPassword 新密码
 *
 * 使用邮件中的重置令牌设置新密码。
 */
void AuthService::resetPassword(const QString &token, const QString &newPassword)
{
    m_pendingOperation = "reset_password";

    // === 构建密码重置请求 ===
    /* 密码重置请求示例：
     * POST /api/v1/auth/reset-password
     * Content-Type: application/json
     *
     * {
     *   "token": "reset_token_from_email_link",
     *   "new_password": "newSecurePassword123"
     * }
     *
     * 预期响应（重置成功）：
     * {
     *   "success": true,
     *   "data": {
     *     "message": "密码重置成功"
     *   }
     * }
     *
     * 预期响应（令牌无效）：
     * {
     *   "success": false,
     *   "error_code": "INVALID_RESET_TOKEN",
     *   "error_message": "重置令牌无效或已过期"
     * }
     */
    QJsonObject data;
    data["token"] = token;              // 重置令牌
    data["new_password"] = newPassword; // 新密码

    // 注意：这个API端点可能需要根据实际后端实现调整
    m_apiClient->post("/api/v1/auth/reset-password", data);
}

void AuthService::onApiResponse(const QString &endpoint, const ApiClient::ApiResponse &response)
{
    if (m_pendingOperation == "register") {
        handleRegisterResponse(response);
    }
    else if (m_pendingOperation == "login") {
        handleLoginResponse(response);
    }
    else if (m_pendingOperation == "logout") {
        handleLogoutResponse(response);
    }
    else if (m_pendingOperation == "validate") {
        handleValidateResponse(response);
    }
    else if (m_pendingOperation == "forgot_password") {
        handleForgotPasswordResponse(response);
    }
    else if (m_pendingOperation == "reset_password") {
        handleResetPasswordResponse(response);
    }

    m_pendingOperation.clear();
}

/**
 * @brief 处理登录响应
 * @param response API服务器的登录响应
 *
 * 解析登录响应，提取令牌和用户信息，并保存到本地存储。
 */
void AuthService::handleLoginResponse(const ApiClient::ApiResponse &response)
{
    if (response.success) {
        // === 提取和保存令牌 ===
        /* 从登录响应中提取令牌的过程：
         * 服务器响应示例：
         * {
         *   "success": true,
         *   "data": {
         *     "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
         *     "refresh_token": "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
         *     "user_info": {
         *       "user_id": 123,
         *       "username": "player123",
         *       "email": "player@example.com",
         *       "role": "user",
         *       "status": "active",
         *       "permissions": ["read", "write", "game_access"]
         *     }
         *   }
         * }
         *
         * 提取过程：
         * 1. response.data["token"] → 访问令牌字符串
         * 2. response.data["refresh_token"] → 刷新令牌字符串
         * 3. response.data["user_info"] → 用户信息JSON对象
         */
        // === 根据AUTH_SERVICE_API.md响应格式解析令牌 ===
        qDebug() << "AuthService: 解析登录响应数据";
        qDebug() << "  响应数据键:" << response.data.keys();

        QString token;
        QString refreshToken;
        QJsonObject userInfo;

        // === 优先从根级别获取令牌 ===
        if (response.data.contains("access_token")) {
            // 直接从根级别获取access_token
            token = response.data["access_token"].toString();
            refreshToken = response.data["refresh_token"].toString();
            userInfo = response.data["user_info"].toObject();
            qDebug() << "  使用根级别 - access_token字段";
        } else if (response.data.contains("session")) {
            // 尝试从session对象获取
            QJsonObject session = response.data["session"].toObject();
            token = session["access_token"].toString();
            refreshToken = session["refresh_token"].toString();
            userInfo = response.data["user_info"].toObject();
            qDebug() << "  使用session格式 - session.access_token字段";
        } else {
            // 兼容旧格式
            token = response.data["token"].toString();
            refreshToken = response.data["refresh_token"].toString();
            userInfo = response.data["user_info"].toObject();
            qDebug() << "  使用旧格式 - token字段";
        }

        qDebug() << "  提取的访问令牌长度:" << token.length();
        qDebug() << "  提取的刷新令牌长度:" << refreshToken.length();

        // === 调试令牌信息 ===
        qDebug() << "AuthService: 登录成功，设置访问令牌";
        qDebug() << "  访问令牌长度:" << token.length();
        qDebug() << "  访问令牌前缀:" << (token.length() > 20 ? token.left(20) + "..." : token);
        qDebug() << "  刷新令牌长度:" << refreshToken.length();

        // 将令牌设置到API客户端，用于后续的认证请求
        m_apiClient->setToken(token);
        m_apiClient->setRefreshToken(refreshToken);

        // === 验证令牌是否设置成功 ===
        QString verifyToken = m_apiClient->getToken();
        qDebug() << "  验证设置后的令牌长度:" << verifyToken.length();
        qDebug() << "  ApiClient认证状态:" << m_apiClient->isAuthenticated();
        saveUserInfo(userInfo);                     // 保存到本地存储
        m_currentUser = parseUserInfo(userInfo);    // 解析为UserInfo结构体

        // === 发出登录成功信号 ===
        emit loginSucceeded(m_currentUser);
    } else {
        // === 登录失败处理 ===
        /* 登录失败响应示例：
         * {
         *   "success": false,
         *   "error_message": "用户名或密码错误",
         *   "error_code": "INVALID_CREDENTIALS"
         * }
         */
        emit loginFailed(response.errorMessage);
    }
}

void AuthService::handleRegisterResponse(const ApiClient::ApiResponse &response)
{
    if (response.success) {
        emit registerSucceeded();
    } else {
        emit registerFailed(response.errorMessage);
    }
}

void AuthService::handleLogoutResponse(const ApiClient::ApiResponse &response)
{
    clearUserInfo();
    emit logoutCompleted();
}

void AuthService::handleValidateResponse(const ApiClient::ApiResponse &response)
{
    if (response.success) {
        m_currentUser = parseUserInfo(response.data);
        emit tokenValidated(m_currentUser);
    } else {
        emit tokenExpired();
    }
}

void AuthService::handleForgotPasswordResponse(const ApiClient::ApiResponse &response)
{
    if (response.success) {
        emit forgotPasswordSucceeded();
    } else {
        emit forgotPasswordFailed(response.errorMessage);
    }
}

void AuthService::handleResetPasswordResponse(const ApiClient::ApiResponse &response)
{
    if (response.success) {
        emit resetPasswordSucceeded();
    } else {
        emit resetPasswordFailed(response.errorMessage);
    }
}

void AuthService::onAuthenticationRequired()
{
    clearUserInfo();
    emit authenticationRequired();
}

void AuthService::onTokenRefreshed(const QString &newToken)
{
    qDebug() << "Token refreshed successfully";
}

/**
 * @brief 保存用户信息到本地存储
 * @param userInfo 用户信息的JSON对象
 *
 * 将用户信息序列化为JSON并保存到QSettings，以便应用重启后恢复。
 */
void AuthService::saveUserInfo(const QJsonObject &userInfo)
{
    /* 用户信息保存过程：
     * 输入JSON对象示例：
     * {
     *   "user_id": 123,
     *   "username": "player123",
     *   "email": "player@example.com",
     *   "role": "user",
     *   "status": "active",
     *   "last_login": "2024-01-01T12:00:00Z",
     *   "login_count": 42,
     *   "created_at": "2023-06-15T10:30:00Z",
     *   "email_verified": true,
     *   "permissions": ["read", "write", "game_access"]
     * }
     *
     * 序列化过程：
     * 1. QJsonObject → QJsonDocument
     * 2. QJsonDocument → QByteArray (JSON字符串的字节表示)
     * 3. QByteArray → QSettings存储
     *
     * 最终存储格式（QSettings中的"user_info"键）：
     * QByteArray: "{\"user_id\":123,\"username\":\"player123\",\"email\":\"player@example.com\",...}"
     */
    QSettings settings;
    QJsonDocument doc(userInfo);                    // 创建JSON文档
    settings.setValue("user_info", doc.toJson());   // 序列化为字节数组并保存
}

/**
 * @brief 清除用户信息和认证状态
 *
 * 清除所有本地存储的用户数据和认证令牌，用于登出操作。
 */
void AuthService::clearUserInfo()
{
    // === 清除API客户端的令牌 ===
    m_apiClient->clearTokens();     // 清除访问令牌和刷新令牌

    // === 重置当前用户信息 ===
    m_currentUser = UserInfo{};     // 重置为默认的空用户信息

    // === 清除本地存储 ===
    /* 清除过程：
     * 1. 从QSettings中删除"user_info"键
     * 2. 这会删除所有保存的用户信息JSON数据
     * 3. 下次启动应用时不会自动恢复登录状态
     */
    QSettings settings;
    settings.remove("user_info");  // 删除本地存储的用户信息
}

/**
 * @brief 解析用户信息JSON对象
 * @param data 包含用户信息的JSON对象
 * @return 解析后的UserInfo结构体
 *
 * 将从服务器或本地存储获取的JSON用户信息转换为UserInfo结构体。
 */
AuthService::UserInfo AuthService::parseUserInfo(const QJsonObject &data) const
{
    /* JSON到UserInfo的解析过程：
     * 输入JSON对象示例：
     * {
     *   "user_id": 123,
     *   "username": "player123",
     *   "email": "player@example.com",
     *   "last_login": "2024-01-01T12:00:00Z",
     *   "status": "active",
     *   "login_count": 42,
     *   "created_at": "2023-06-15T10:30:00Z",
     *   "role": "user",
     *   "email_verified": true,
     *   "permissions": ["read", "write", "game_access", "chat"]
     * }
     *
     * 解析过程：
     * 1. 基本字段：直接从JSON提取对应类型的值
     * 2. 权限数组：遍历JSON数组，转换为QStringList
     * 3. 类型转换：JSON值自动转换为C++对应类型
     */
    UserInfo info;

    // === 基本用户信息字段解析 ===
    info.userId = data["user_id"].toInt();                     // 123
    info.username = data["username"].toString();               // "player123"
    info.email = data["email"].toString();                     // "player@example.com"
    info.lastLogin = data["last_login_at"].toString();            // "2024-01-01T12:00:00Z"
    if (info.lastLogin.isEmpty()) {
        info.lastLogin = data["last_login"].toString();           // 备用字段名
    }
    info.status = data["status"].toString();                   // "active"
    info.loginCount = data["login_count"].toInt();             // 42
    info.createdAt = data["created_at"].toString();            // "2023-06-15T10:30:00Z"
    info.role = data["role"].toString();                       // "user"
    info.emailVerified = data["email_verified"].toBool();      // true

    // === 权限列表解析 ===
    /* 权限数组解析过程：
     * JSON数组：["read", "write", "game_access", "chat"]
     *
     * 解析步骤：
     * 1. data["permissions"] → QJsonValue
     * 2. QJsonValue.toArray() → QJsonArray
     * 3. 遍历数组中的每个QJsonValue
     * 4. QJsonValue.toString() → QString
     * 5. 添加到QStringList
     *
     * 最终结果：QStringList{"read", "write", "game_access", "chat"}
     */
    QJsonArray permissionsArray = data["permissions"].toArray();
    for (const QJsonValue &value : permissionsArray) {
        info.permissions.append(value.toString());
    }

    return info;
}

bool AuthService::isAuthenticated() const
{
    return m_apiClient->isAuthenticated();
}

AuthService::UserInfo AuthService::getCurrentUser() const
{
    return m_currentUser;
}

QString AuthService::getToken() const
{
    return m_apiClient->getToken();
}

ApiClient* AuthService::getApiClient() const
{
    return m_apiClient;
}
